home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / amiga.free / sorgenti vari / wolfedit2 2.0.4 source.sit / WolfEdit2 2.0.4 Source / UMapView.p < prev    next >
Text File  |  1996-06-16  |  23KB  |  996 lines

  1. unit UMapView;
  2.  
  3. interface
  4.     uses
  5.         UGoof, UList, UPalette, UScrap, UWolfDoc, UMapCellsView, UMapPalette;
  6.  
  7. {$SETC MonitorDrawCell = FALSE}
  8.  
  9.     const
  10.  
  11.         numTools = 7;
  12.  
  13.         selectTool = 0;
  14.         pencilTool = 1;
  15.         eraserTool = 2;
  16.         dropperTool = 3;
  17.         paintPotTool = 4;
  18.         rectangleTool = 5;
  19.         soundTool = 6;
  20.         quarterPencilTool = 7;
  21.  
  22.         toolCursIDBase = 128;
  23.         handCursID = 258;
  24.  
  25.     type
  26.  
  27.         TMapView = object(TMapCellsView)
  28.                 fMap: TMap;
  29.                 fMagnification: integer;
  30.                 fPalette: TMapPalette;
  31.                 fTools: TPalette;
  32.                 fFloating: TMapCells;
  33.                 fUndo: TMapViewUndo;
  34.                 procedure IMapView (itsMap: TMap);
  35.                 procedure Free;
  36.                 override;
  37.                 procedure Close;
  38.                 function CurrentCode: MapCell;
  39.                 function CurrentTool: integer;
  40.                 procedure SetMagnification (n: integer);
  41.                 procedure Key (var e: EventInfo);
  42.                 override;
  43.                 procedure Click (var e: EventInfo);
  44.                 override;
  45.                 procedure TMapView.MakeFloating (clearUnder: boolean);
  46.                 procedure TMapView.DoDrag (e: EventInfo; cell: Point);
  47.                 procedure TMapView.DoPencil (cell: Point);
  48.                 procedure TMapView.PencilCell (cell: Point; initCode, pencilCode, pencilMask: MapCell);
  49.                 procedure TMapView.DoEraser (cell: Point);
  50.                 procedure TMapView.DoDropper (cell: Point);
  51.                 procedure TMapView.DoPaintPot (cell: Point);
  52.                 procedure TMapView.DoRectangle (r: Rect);
  53.                 procedure TMapView.DoSound (cell: Point);
  54.                 function TrackCell (var cell: Point): boolean;
  55.                 procedure TMapView.SetCell (cell: Point; code: MapCell);
  56.         {$IFC MonitorDrawCell}
  57.                 procedure TMapView.DrawCell (cell: Point; r: Rect; var hilite: boolean);
  58.                 override;
  59.         {$ENDC}
  60.                 function GetCellForDrawing (cell: Point): MapCell;
  61.                 override;
  62.                 procedure TMapView.SetupMenus;
  63.                 override;
  64.                 procedure TMapView.DoMenuCommand (cmdNumber: integer);
  65.                 override;
  66.                 procedure TMapView.DoUndo;
  67.                 procedure TMapView.DoCut;
  68.                 procedure TMapView.DoCopy;
  69.                 procedure TMapView.DoPaste;
  70.                 procedure TMapView.DoClear;
  71.                 procedure TMapView.DoFlipHorizontal;
  72.                 procedure TMapView.DoFlipVertical;
  73.                 procedure TMapView.RotateSelection (procedure RotateRC (row, col: integer; r2: Rect; var p2: Point); rot: integer);
  74.                 procedure TMapView.DoRotateLeft;
  75.                 procedure TMapView.DoRotateRight;
  76.                 procedure TMapView.DoSpecialEffects;
  77.                 procedure TMapView.DoGetInfo;
  78.                 procedure TMapView.DoLevelStatus;
  79.                 procedure TMapView.ClearCells (r: Rect);
  80.                 procedure TMapView.FillCells (r: Rect; cell: MapCell);
  81.                 procedure SaveForUndo (r: Rect);
  82.                 procedure SaveCellForUndo (cell: Point);
  83.                 procedure SaveAllForUndo;
  84.                 procedure DropFloating;
  85.                 procedure DiscardFloating;
  86.                 procedure DiscardUndo;
  87.                 procedure TMapView.UpdateCursor;
  88.                 procedure TMapView.Idle;
  89.                 override;
  90.             end;
  91.  
  92.         TMapViewUndo = object(TObject)
  93.                 fNext: TMapViewUndo;
  94.                 fCells: TMapCells;
  95.             end;
  96.  
  97.     procedure IUMapView;
  98.  
  99. implementation
  100.     uses
  101. {$IFC Demo}
  102.         UDemo, 
  103. {$ENDC}
  104.         HexIO, UCursors, UMapListDoc, UMapListView, USoundDialog, {}
  105.         USpecialEffects, ULevelStatus;
  106.  
  107.     const
  108.  
  109.         minCellSize = 16;
  110.         fontNum = geneva;
  111.         fontSize = 9;
  112.  
  113.         toolIconIDBase = 128;
  114.         wallPatListIDBase = 129;
  115.  
  116.         flipHorizontalCmd = 350;
  117.         flipVerticalCmd = 351;
  118.         rotateLeftCmd = 352;
  119.         rotateRightCmd = 353;
  120.  
  121.         levelStatusCmd = 360;
  122.  
  123.         specialEffectsCmd = 409;
  124.  
  125. {$IFC NOT Demo}
  126.     procedure DoQuarterPencil (v: TMapView; cell: Point);
  127.         var
  128.             code: MapCell;
  129.             r1, r2, r3: Rect;
  130.             p: Point;
  131.             quarter: integer;
  132.     begin
  133.         with v do begin
  134.                 DiscardUndo;
  135.                 SaveCellForUndo(cell);
  136.                 code := fMap.GetCell(cell);
  137.                 CellToRect(cell, r1);
  138.                 SetRect(r2, 0, 0, 1, 1);
  139.                 p := gLastEvent.where;
  140.                 MapPt(p, r1, r2);
  141.                 quarter := BSL(1, p.v * 2 + p.h);
  142.                 code.missingQuarters := BXOR(code.missingQuarters, quarter);
  143.                 fMap.SetCell(cell, code);
  144.                 SetRect(r3, p.h, p.v, p.h + 1, p.v + 1);
  145.                 SetRect(r2, 0, 0, 2, 2);
  146.                 MapRect(r3, r2, r1);
  147.                 InvalidateRect(r3);
  148.                 fMap.Changed;
  149.             end;
  150.     end;
  151. {$ENDC}
  152.  
  153.     procedure TMapView.IMapView (itsMap: TMap);
  154.         var
  155.             i: integer;
  156.             cells: TMapCells;
  157.             palette: TMapPalette;
  158.             tools: TPalette;
  159.     begin
  160.         cells := nil;
  161.         if itsMap <> nil then
  162.             cells := itsMap.fCells;
  163.         IMapCellsView(cells, [listMultiSel, listMarquee], itsMap.fMapList);
  164.         fMap := itsMap;
  165.         if itsMap <> nil then
  166.             itsMap.fView := self;
  167.         fPalette := nil;
  168.         fTools := nil;
  169.         fFloating := nil;
  170.         fUndo := nil;
  171.         SetMagnification(1);
  172.         new(palette);
  173.         palette.IMapPalette(itsMap.fMapList);
  174.         fPalette := palette;
  175.         new(tools);
  176.         tools.IPalette(32, 32, 1, numTools, true);
  177.         fTools := tools;
  178.         for i := 0 to numTools - 1 do
  179.             fTools.SetCellIcon(i, GetResource('ICON', toolIconIDBase + i));
  180.     end;
  181.  
  182.     procedure TMapView.Free;
  183.     begin
  184.         if fMap <> nil then
  185.             fMap.fView := nil;
  186.         DiscardFloating;
  187.         DiscardUndo;
  188.         inherited Free;
  189.     end;
  190.  
  191.     procedure TMapView.Close;
  192.     begin
  193.         if fMap <> nil then begin
  194.                 DropFloating;
  195.                 fMap.Close;
  196.             end;
  197.     end;
  198.  
  199.     function TMapView.CurrentCode: MapCell;
  200.         var
  201.             code, mask: MapCell;
  202.     begin
  203.         fPalette.GetCurrentCodeAndMask(code, mask);
  204.         CurrentCode := code;
  205.     end;
  206.  
  207.     function TMapView.CurrentTool: integer;
  208.         var
  209.             tool: integer;
  210.     begin
  211.         tool := fTools.GetSelection;
  212.         if gLastEvent.theOptionKey then begin
  213. {$IFC NOT Demo}
  214.                 if gLastEvent.theCmdKey and (tool = pencilTool) then
  215.                     tool := quarterPencilTool
  216.                 else
  217. {$ENDC}
  218.                     case tool of
  219.                         pencilTool, paintPotTool, rectangleTool: 
  220.                             tool := dropperTool;
  221.                         otherwise
  222.                             ;
  223.                     end;
  224.             end;
  225.         CurrentTool := tool;
  226.     end;
  227.  
  228.     procedure TMapView.SetMagnification (n: integer);
  229.         var
  230.             size: integer;
  231.             r: Rect;
  232.     begin
  233.         fMagnification := n;
  234.         size := n * minCellSize;
  235.         SetCellSize(size, size);
  236.     end;
  237.  
  238. {$IFC MonitorDrawCell}
  239.     procedure TMapView.DrawCell (cell: Point; r: Rect; var hilite: boolean);
  240.     begin
  241.         if Button then
  242.             writeln('TMapView.DrawCell([', cell.h : 1, ',', cell.v : 1, '])');
  243.         inherited DrawCell(cell, r, hilite);
  244.     end;
  245. {$ENDC}
  246.  
  247.     procedure TMapView.Key (var e: EventInfo);
  248.     begin
  249.         if (e.theChar = chr(8)) | (e.theChar = chr($7F)) then
  250.             DoClear;
  251.     end;
  252.  
  253.     procedure TMapView.Click (var e: EventInfo);
  254.         var
  255.             tool: integer;
  256.             cell: Point;
  257.     begin
  258.         if FindCell(e.where, cell) then begin
  259.                 tool := CurrentTool;
  260.                 case tool of
  261.                     selectTool: 
  262.                         if PtInRect(cell, fSelection) then
  263.                             DoDrag(e, cell)
  264.                         else begin
  265.                                 DropFloating;
  266.                                 inherited Click(e);
  267.                             end;
  268.                     pencilTool: 
  269.                         DoPencil(cell);
  270.                     eraserTool: 
  271.                         DoEraser(cell);
  272.                     dropperTool: 
  273.                         DoDropper(cell);
  274.                     paintPotTool: 
  275.                         DoPaintPot(cell);
  276.                     rectangleTool:  begin
  277.                             DropFloating;
  278.                             inherited Click(e);
  279.                             DoRectangle(fSelection);
  280.                         end;
  281.                     soundTool: 
  282.                         DoSound(cell);
  283. {$IFC NOT Demo}
  284.                     quarterPencilTool: 
  285.                         DoQuarterPencil(self, cell);
  286. {$ENDC}
  287.                     otherwise
  288.                         ;
  289.                 end;
  290.             end;
  291.     end;
  292.  
  293.     procedure TMapView.MakeFloating (clearUnder: boolean);
  294.         var
  295.             stone: MapCell;
  296.             floating: TMapCells;
  297.     begin
  298.         if (fFloating = nil) & not EmptyRect(fSelection) then begin
  299.                 new(floating);
  300.                 floating.IMapCells(fSelection);
  301.                 fFloating := floating;
  302.                 fMap.CopyTo(fFloating);
  303.                 if clearUnder then begin
  304.                         ClearCell(stone);
  305.                         stone.wall := $81;
  306.                         DiscardUndo;
  307.                         SaveForUndo(fSelection);
  308.                         FillCells(fSelection, stone);
  309.                     end;
  310.             end
  311.     end;
  312.  
  313.     procedure TMapView.DoDrag (e: EventInfo; cell: Point);
  314.         var
  315.             cell2: Point;
  316.             rgn1, rgn2: RgnHandle;
  317.             b, r1, r2, cr1, cr2: Rect;
  318.     begin
  319.         rgn1 := NewRgn;
  320.         rgn2 := NewRgn;
  321.         if fFloating = nil then
  322.             MakeFloating(not e.theOptionKey)
  323.         else if e.theOptionKey then begin
  324.                 DiscardUndo;
  325.                 SaveForUndo(fSelection);
  326.                 fMap.CopyFrom(fFloating);
  327.             end;
  328.         cell2 := cell;
  329.         while TrackCell(cell2) do begin
  330.                 fFloating.GetBounds(b);
  331.                 CellsToRect(b, r1);
  332.                 OffsetRect(b, cell2.h - cell.h, cell2.v - cell.v);
  333.                 CellsToRect(b, r2);
  334.                 fFloating.Position(b.topLeft);
  335.                 ClearSelection;
  336.                 ForeColor(blackColor);
  337.                 BackColor(whiteColor);
  338.                 if SectRect(thePort^.clipRgn^^.rgnBBox, r1, cr1) then begin
  339.                         cr2 := cr1;
  340.                         OffsetRect(cr2, r2.left - r1.left, r2.top - r1.top);
  341.                         CopyBits(thePort^.portBits, thePort^.portBits, cr1, cr2, srcCopy, nil);
  342.                     end;
  343.                 RectRgn(rgn1, r1);
  344.                 RectRgn(rgn2, r2);
  345.                 UnionRgn(rgn1, rgn2, rgn1);
  346.                 RectRgn(rgn2, cr2);
  347.                 DiffRgn(rgn1, rgn2, rgn1);
  348.                 InvalidateRgn(rgn1);
  349.                 SetSelectionRect(b);
  350.                 Update;
  351.                 cell := cell2;
  352.             end;
  353.         DisposeRgn(rgn1);
  354.         DisposeRgn(rgn2);
  355.     end;
  356.  
  357.     procedure TMapView.DoPencil (cell: Point);
  358.         var
  359.             initCode, pencilCode, pencilMask: MapCell;
  360.     begin
  361.         DiscardUndo;
  362.         initCode := fMap.GetCell(cell);
  363.         fPalette.GetCurrentCodeAndMask(pencilCode, pencilMask);
  364.         if gLastEvent.theShiftKey then begin
  365.                 if pencilCode.wall = 0 then
  366.                     pencilMask.wall := 0;
  367.                 if pencilCode.obj = 0 then
  368.                     pencilMask.obj := 0;
  369.             end;
  370.         repeat
  371.             PencilCell(cell, initCode, pencilCode, pencilMask);
  372.         until not TrackCell(cell);
  373.         fMap.Changed;
  374.     end;
  375.  
  376.     procedure TMapView.PencilCell (cell: Point; initCode, pencilCode, pencilMask: MapCell);
  377.         var
  378.             pencilItem: integer;
  379.             code: MapCell;
  380.     begin
  381.         code := fCells.GetCell(cell);
  382.         if EqualCode(pencilCode, AndCode(initCode, pencilMask)) then
  383.             code := AndCode(code, NotCode(pencilMask))
  384.         else
  385.             code := OrCode(pencilCode, AndCode(code, NotCode(pencilMask)));
  386.         SaveCellForUndo(cell);
  387.         SetCell(cell, code);
  388.     end;
  389.  
  390.     procedure TMapView.DoEraser (cell: Point);
  391.         var
  392.             empty: MapCell;
  393.     begin
  394.         DiscardUndo;
  395.         ClearCell(empty);
  396.         repeat
  397.             SaveCellForUndo(cell);
  398.             SetCell(cell, empty);
  399.         until not TrackCell(cell);
  400.         fMap.Changed;
  401.     end;
  402.  
  403.     procedure TMapView.DoDropper (cell: Point);
  404.     begin
  405.         fPalette.SelectByExample(fCells.GetCell(cell));
  406.     end;
  407.  
  408.     procedure TMapView.DoPaintPot (cell: Point);
  409.         var
  410.             initCode, paintCode: MapCell;
  411.  
  412.         procedure Fill (row, col: integer);
  413.             var
  414.                 cell: Point;
  415.                 code: MapCell;
  416.         begin
  417.             SetPt(cell, col, row);
  418.             code := fCells.GetCell(cell);
  419.             if EqualCode(code, initCode) then begin
  420.                     SetCell(cell, paintCode);
  421.                     if row > 0 then
  422.                         Fill(row - 1, col);
  423.                     if row < 63 then
  424.                         Fill(row + 1, col);
  425.                     if col > 0 then
  426.                         Fill(row, col - 1);
  427.                     if col < 63 then
  428.                         Fill(row, col + 1);
  429.                 end;
  430.         end;
  431.  
  432.     begin {DoPaintPot}
  433.         initCode := fCells.GetCell(cell);
  434.         paintCode := CurrentCode;
  435.         if not EqualCode(paintCode, initCode) then begin
  436.                 ChangeCursor(gWatch);
  437.                 DiscardUndo;
  438.                 SaveAllForUndo;
  439.                 Fill(cell.v, cell.h);
  440.                 fMap.Changed;
  441.             end;
  442.     end;
  443.  
  444.     procedure TMapView.DoRectangle (r: Rect);
  445.         var
  446.             border: MapCell;
  447.             x, y: integer;
  448.  
  449.         procedure SetBorder (x, y: integer);
  450.             var
  451.                 cell: Point;
  452.         begin
  453.             SetPt(cell, x, y);
  454.             fMap.SetCell(cell, border);
  455.         end;
  456.  
  457.     begin {TMapView.DoRectangle}
  458.         if not EmptyRect(r) then begin
  459.                 DiscardUndo;
  460.                 SaveForUndo(r);
  461.                 ClearCells(r);
  462.                 border := CurrentCode;
  463.                 for x := r.left to r.right - 1 do begin
  464.                         SetBorder(x, r.top);
  465.                         SetBorder(x, r.bottom - 1);
  466.                     end;
  467.                 for y := r.top + 1 to r.bottom - 2 do begin
  468.                         SetBorder(r.left, y);
  469.                         SetBorder(r.right - 1, y);
  470.                     end;
  471.                 fMap.Changed;
  472.                 InvalidateCells(r);
  473.             end;
  474.     end;
  475.  
  476.     procedure TMapView.DoSound (cell: Point);
  477.         var
  478.             code: MapCell;
  479.     begin
  480.         code := fCells.GetCell(cell);
  481.         if EditSoundArea(code) then begin
  482.                 SetCell(cell, code);
  483.                 fMap.Changed;
  484.             end;
  485.     end;
  486.  
  487.     procedure TMapView.SetCell (cell: Point; code: MapCell);
  488.         var
  489.             item: integer;
  490.     begin
  491.         item := ExtractObject(code);
  492.         if (item >= $13) & (item <= $16) & fMap.fStartPosSet then
  493.             InvalidateCell(fMap.fStartPos);
  494.         fMap.SetCell(cell, code);
  495.         UpdateCell(cell);
  496.     end;
  497.  
  498.     function TMapView.GetCellForDrawing (cell: Point): MapCell;
  499.     begin
  500.         if (fFloating <> nil) & (PtInRect(cell, fFloating.fH^^.bounds)) then
  501.             GetCellForDrawing := fFloating.GetCell(cell)
  502.         else
  503.             GetCellForDrawing := inherited GetCellForDrawing(cell);
  504.     end;
  505.  
  506.   {        Track the mouse until it enters a different cell or        }
  507.   {        the button is released. Returns true if a new cell is    }
  508.   {        entered with the button down.                                    }
  509.  
  510.     function TMapView.TrackCell (var cell: Point): boolean;
  511.         var
  512.             mouse, cell0: Point;
  513.     begin
  514.         cell0 := cell;
  515.         while StillDown do begin
  516.                 AutoScroll;
  517.                 GetMouse(mouse);
  518.                 if FindCell(mouse, cell) then
  519.                     if not EqualPt(cell, cell0) then begin
  520.                             TrackCell := true;
  521.                             exit(TrackCell);
  522.                         end;
  523.             end;
  524.         TrackCell := false;
  525.     end;
  526.  
  527.     procedure TMapView.DoUndo;
  528.         var
  529.             r: Rect;
  530.             p, q: TMapViewUndo;
  531.     begin
  532.         DropFloating;
  533.         p := fUndo;
  534.         fUndo := nil;
  535.         while p <> nil do begin
  536.                 q := p;
  537.                 p := p.fNext;
  538.                 q.fCells.GetBounds(r);
  539.                 SaveForUndo(r);
  540.                 fMap.CopyFrom(q.fCells);
  541.                 q.fCells.Free;
  542.                 q.Free;
  543.                 InvalidateCells(r);
  544.             end;
  545.         ClearSelection;
  546.     end;
  547.  
  548.     procedure TMapView.DoCut;
  549.     begin
  550.         DoCopy;
  551.         DoClear;
  552.     end;
  553.  
  554.     procedure TMapView.DoCopy;
  555.         var
  556.             r: Rect;
  557.             c: TMapCells;
  558.             pict: PicHandle;
  559.             row, col: integer;
  560.             p: Point;
  561.             hilite: boolean;
  562.     begin
  563.         r := fSelection;
  564.         if fFloating <> nil then
  565.             fFloating.WriteToScrap
  566.         else begin
  567.                 new(c);
  568.                 c.IMapCells(r);
  569.                 fMap.CopyTo(c);
  570.                 c.WriteToScrap;
  571.                 c.Free;
  572.             end;
  573.         if gLastEvent.theOptionKey then begin
  574.                 Focus;
  575.                 with fSelection do
  576.                     SetRect(r, 16 * left, 16 * top, 16 * right, 16 * bottom);
  577.                 pict := OpenPicture(r);
  578.                 if pict <> nil then begin
  579.                         for row := fSelection.top to fSelection.bottom - 1 do
  580.                             for col := fSelection.left to fSelection.right - 1 do begin
  581.                                     SetPt(p, col, row);
  582.                                     SetRect(r, 16 * col, 16 * row, 16 * (col + 1), 16 * (row + 1));
  583.                                     hilite := false;
  584.                                     DrawCell(p, r, hilite);
  585.                                 end;
  586.                         ClosePicture;
  587.                         WriteScrap('PICT', pict);
  588.                         DisposHandle(Handle(pict));
  589.                     end;
  590.             end;
  591.     end;
  592.  
  593.     procedure TMapView.DoPaste;
  594.         var
  595.             r, cells: Rect;
  596.             p: Point;
  597.             floating: TMapCells;
  598.     begin
  599.         DropFloating;
  600.         DiscardUndo;
  601.         new(floating);
  602.         floating.IFromScrap;
  603.         fFloating := floating;
  604.         if not EmptyRect(fSelection) then
  605.             fFloating.Position(fSelection.topLeft);
  606.         fFloating.GetBounds(cells);
  607.         CellsToRect(cells, r);
  608.         SetPt(p, r.right - r.left, r.bottom - r.top);
  609.         if fFrame <> nil then
  610.             fFrame.RevealRect(r, p);
  611.         SetSelectionRect(cells);
  612.         InvalidateRect(r);
  613.     end;
  614.  
  615.     procedure TMapView.DoClear;
  616.         var
  617.             r: Rect;
  618.     begin
  619.         r := fSelection;
  620.         if fFloating <> nil then
  621.             DiscardFloating
  622.         else begin
  623.                 DiscardUndo;
  624.                 SaveForUndo(r);
  625.                 ClearCells(r);
  626.                 fMap.Changed;
  627.             end;
  628.         ClearSelection;
  629.         InvalidateCells(r);
  630.     end;
  631.  
  632.     procedure TMapView.DoSpecialEffects;
  633.         var
  634.             r: Rect;
  635.             cell0, cell: MapCell;
  636.             c: Point;
  637.             row, col: integer;
  638.     begin
  639. {$IFC Demo}
  640.         OnlyInFullVersion;
  641. {$ELSEC}
  642.         DropFloating;
  643.         r := fSelection;
  644.         cell0 := fMap.GetCell(r.topLeft);
  645.         if EditSpecialEffects(cell0) then begin
  646.                 DiscardUndo;
  647.                 SaveForUndo(r);
  648.                 for row := r.top to r.bottom - 1 do
  649.                     for col := r.left to r.right - 1 do begin
  650.                             SetPt(c, col, row);
  651.                             cell := fMap.GetCell(c);
  652.                             cell.flushDoor := cell0.flushDoor;
  653.                             cell.noDoorSide := cell0.noDoorSide;
  654.                             cell.missingQuarters := cell0.missingQuarters;
  655.                             if cell0.flushDoor then
  656.                                 cell.dir := cell0.dir;
  657.                             fMap.SetCell(c, cell);
  658.                         end;
  659.                 InvalidateCells(fSelection);
  660.                 fMap.Changed;
  661.             end;
  662. {$ENDC}
  663.     end;
  664.  
  665.     procedure TMapView.DoGetInfo;
  666.     begin
  667.         GetInfoForLevel(fMap.fMapList.fView, fMap.fLevelNumber);
  668.     end;
  669.  
  670.     procedure TMapView.ClearCells (r: Rect);
  671.         var
  672.             empty: MapCell;
  673.             row, col: integer;
  674.     begin
  675.         ClearCell(empty);
  676.         FillCells(r, empty);
  677.         for row := r.top to r.bottom - 1 do
  678.             for col := r.left to r.right - 1 do
  679.                 fMap.SetRowCol(row, col, empty);
  680.     end;
  681.  
  682.     procedure TMapView.FillCells (r: Rect; cell: MapCell);
  683.         var
  684.             row, col: integer;
  685.     begin
  686.         for row := r.top to r.bottom - 1 do
  687.             for col := r.left to r.right - 1 do
  688.                 fMap.SetRowCol(row, col, cell);
  689.     end;
  690.  
  691.     procedure TMapView.SaveForUndo (r: Rect);
  692.         var
  693.             u: TMapViewUndo;
  694.             c: TMapCells;
  695.     begin
  696.         new(u);
  697.         u.fNext := fUndo;
  698.         fUndo := u;
  699.         new(c);
  700.         c.IMapCells(r);
  701.         u.fCells := c;
  702.         fMap.CopyTo(u.fCells);
  703.     end;
  704.  
  705.     procedure TMapView.SaveCellForUndo (cell: Point);
  706.         var
  707.             cells: Rect;
  708.     begin
  709.         CellToCells(cell, cells);
  710.         SaveForUndo(cells);
  711.     end;
  712.  
  713.     procedure TMapView.SaveAllForUndo;
  714.         var
  715.             cells: Rect;
  716.     begin
  717.         SetRect(cells, 0, 0, 64, 64);
  718.         SaveForUndo(cells);
  719.     end;
  720.  
  721.     procedure TMapView.DropFloating;
  722.         var
  723.             r: Rect;
  724.     begin
  725.         if fFloating <> nil then begin
  726.                 fFloating.GetBounds(r);
  727.                 SaveForUndo(r);
  728.                 fMap.CopyFrom(fFloating);
  729.                 fMap.Changed;
  730.                 DiscardFloating;
  731.             end;
  732.     end;
  733.  
  734.     procedure TMapView.DiscardUndo;
  735.         var
  736.             u: TMapViewUndo;
  737.     begin
  738.         while fUndo <> nil do begin
  739.                 u := fUndo;
  740.                 fUndo := u.fNext;
  741.                 u.fCells.Free;
  742.                 u.Free;
  743.             end;
  744.     end;
  745.  
  746.     procedure TMapView.DiscardFloating;
  747.     begin
  748.         if fFloating <> nil then begin
  749.                 fFloating.Free;
  750.                 fFloating := nil;
  751.             end;
  752.     end;
  753.  
  754.     procedure TMapView.SetupMenus;
  755.         var
  756.             len, offset: longint;
  757.     begin
  758.         if (fUndo <> nil) | (fFloating <> nil) then
  759.             EnableCmd(undoCmd);
  760.         if not EmptyRect(fSelection) then begin
  761.                 EnableCmd(cutCmd);
  762.                 EnableCmd(copyCmd);
  763.                 EnableCmd(clearCmd);
  764.                 EnableCmd(specialEffectsCmd);
  765.                 EnableCmd(flipHorizontalCmd);
  766.                 EnableCmd(flipVerticalCmd);
  767.                 EnableCmd(rotateLeftCmd);
  768.                 EnableCmd(rotateRightCmd);
  769.             end;
  770.         len := GetScrap(nil, mapScrapType, offset);
  771.         if len >= 0 then
  772.             EnableCmd(pasteCmd);
  773.         EnableCmd(levelStatusCmd);
  774.         EnableCmd(getLevelInfoCmd);
  775.         EnableCmd(newLevelCmd);
  776.         inherited SetupMenus;
  777.     end;
  778.  
  779.     procedure TMapView.DoMenuCommand (cmdNumber: integer);
  780.     begin
  781.         case cmdNumber of
  782.             undoCmd: 
  783.                 DoUndo;
  784.             cutCmd: 
  785.                 DoCut;
  786.             copyCmd: 
  787.                 DoCopy;
  788.             pasteCmd: 
  789.                 DoPaste;
  790.             clearCmd: 
  791.                 DoClear;
  792.             flipHorizontalCmd: 
  793.                 DoFlipHorizontal;
  794.             flipVerticalCmd: 
  795.                 DoFlipVertical;
  796.             rotateLeftCmd: 
  797.                 DoRotateLeft;
  798.             rotateRightCmd: 
  799.                 DoRotateRight;
  800.             specialEffectsCmd: 
  801.                 DoSpecialEffects;
  802.             levelStatusCmd: 
  803.                 DoLevelStatus;
  804.             getLevelInfoCmd: 
  805.                 DoGetInfo;
  806.             newLevelCmd: 
  807.                 fMap.fMapList.fView.DoMenuCommand(cmdNumber);
  808.         {CreateLevel(fMap.fMapList.fView);}
  809.             otherwise begin
  810.                     DropFloating;
  811.                     ClearSelection;
  812.                     inherited DoMenuCommand(cmdNumber);
  813.                 end;
  814.         end;
  815.     end;
  816.  
  817.     function HFlipCell (cell: MapCell): MapCell;
  818.     begin
  819.         if (cell.obj = $14) | (cell.obj = $16) then
  820.             cell.obj := BXOR(cell.obj, 2);
  821.         if IsSecretDoor(cell) & (BAND(cell.dir, 1) = 1) then
  822.             cell.dir := BXOR(cell.dir, 2);
  823.         HFlipCell := cell;
  824.     end;
  825.  
  826.     function VFlipCell (cell: MapCell): MapCell;
  827.     begin
  828.         if (cell.obj = $13) | (cell.obj = $15) then
  829.             cell.obj := BXOR(cell.obj, 6);
  830.         if IsSecretDoor(cell) & (BAND(cell.dir, 1) = 0) then
  831.             cell.dir := BXOR(cell.dir, 2);
  832.         VFlipCell := cell;
  833.     end;
  834.  
  835.     function RotateCell (cell: MapCell; r: integer): MapCell;
  836.     begin
  837.         if (cell.obj >= $13) & (cell.obj <= $16) then
  838.             cell.obj := (cell.obj - $13 + r) mod 4 + $13;
  839.         if odd(r) & IsDoor(cell) then begin
  840.                 cell.wall := BXOR(cell.wall, 1);
  841.                 cell.obj := BXOR(cell.obj, 1);
  842.             end;
  843.         if IsSecretDoor(cell) then
  844.             cell.dir := (cell.dir + 4 - r) mod 4;
  845.         RotateCell := cell;
  846.     end;
  847.  
  848.     procedure SwapMapCells (cells: TMapCells; row1, col1, row2, col2: integer; function Modify (cell: MapCell): MapCell);
  849.         var
  850.             temp: MapCell;
  851.             p1, p2: Point;
  852.     begin
  853.         SetPt(p1, col1, row1);
  854.         SetPt(p2, col2, row2);
  855.         temp := cells.GetCell(p1);
  856.         cells.SetCell(p1, Modify(cells.GetCell(p2)));
  857.         cells.SetCell(p2, Modify(temp));
  858.     end;
  859.  
  860.     procedure TMapView.DoFlipHorizontal;
  861.         var
  862.             row, off: integer;
  863.     begin
  864.         MakeFloating(true);
  865.         if fFloating <> nil then begin
  866.                 for row := fSelection.top to fSelection.bottom - 1 do
  867.                     for off := 0 to (fSelection.right - fSelection.left + 1) div 2 - 1 do
  868.                         SwapMapCells(fFloating, row, fSelection.left + off, row, fSelection.right - off - 1, HFlipCell);
  869.                 InvalidateCells(fSelection);
  870.             end;
  871.     end;
  872.  
  873.     procedure TMapView.DoFlipVertical;
  874.         var
  875.             col, off: integer;
  876.     begin
  877.         MakeFloating(true);
  878.         if fFloating <> nil then begin
  879.                 for col := fSelection.left to fSelection.right - 1 do
  880.                     for off := 0 to (fSelection.bottom - fSelection.top + 1) div 2 - 1 do
  881.                         SwapMapCells(fFloating, fSelection.top + off, col, fSelection.bottom - off - 1, col, VFlipCell);
  882.                 InvalidateCells(fSelection);
  883.             end;
  884.     end;
  885.  
  886.     procedure TMapView.RotateSelection (procedure RotateRC (row, col: integer; r2: Rect; var p2: Point); rot: integer);
  887.         var
  888.             newCells: TMapCells;
  889.             row, col: integer;
  890.             r1, r2: Rect;
  891.             p1, p2: Point;
  892.     begin
  893.         MakeFloating(true);
  894.         r1 := fSelection;
  895.         SetRect(r2, 0, 0, r1.bottom - r1.top, r1.right - r1.left);
  896.         OffsetRect(r2, r1.left, r1.top);
  897.         new(newCells);
  898.         newCells.IMapCells(r2);
  899.         for row := 0 to r1.bottom - r1.top - 1 do
  900.             for col := 0 to r1.right - r1.left - 1 do begin
  901.                     SetPt(p1, r1.left + col, r1.top + row);
  902.                     RotateRC(row, col, r2, p2);
  903.                     newCells.SetCell(p2, RotateCell(fFloating.GetCell(p1), rot));
  904.                 end;
  905.         fFloating.Free;
  906.         fFloating := newCells;
  907.         SetSelectionRect(r2);
  908.         InvalidateCells(r1);
  909.         InvalidateCells(r2);
  910.     end;
  911.  
  912.     procedure RotateRCLeft (row, col: integer; r2: Rect; var p2: Point);
  913.     begin
  914.         SetPt(p2, r2.left + row, r2.bottom - col - 1);
  915.     end;
  916.  
  917.     procedure RotateRCRight (row, col: integer; r2: Rect; var p2: Point);
  918.     begin
  919.         SetPt(p2, r2.right - row - 1, r2.top + col);
  920.     end;
  921.  
  922.     procedure TMapView.DoRotateLeft;
  923.     begin
  924.         RotateSelection(RotateRCLeft, 3);
  925.     end;
  926.  
  927.     procedure TMapView.DoRotateRight;
  928.     begin
  929.         RotateSelection(RotateRCRight, 1);
  930.     end;
  931.  
  932.     procedure TMapView.DoLevelStatus;
  933.     begin
  934.         ShowLevelStatus(fMap);
  935.     end;
  936.  
  937.     procedure TMapView.UpdateCursor;
  938.         var
  939.             tool: integer;
  940.             pt, cell: Point;
  941.             cursID: integer;
  942.             h: CursHandle;
  943.     begin
  944.         tool := CurrentTool;
  945.         cursID := toolCursIDBase + tool;
  946.         if (tool = selectTool) & not EmptyRect(fSelection) then begin
  947.                 Focus;
  948.                 GetMouse(pt);
  949.                 if FindCell(pt, cell) & PtInRect(cell, fSelection) then
  950.                     cursID := handCursID;
  951.             end;
  952.         h := GetCursor(cursID);
  953.         fFrame.SetCursorHandle(h);
  954.     end;
  955.  
  956.     procedure TMapView.Idle;
  957.         var
  958.             tool: integer;
  959.     begin
  960.         tool := fTools.GetSelection;
  961.         if (tool <> selectTool) & not EmptyRect(fSelection) then begin
  962.                 DropFloating;
  963.                 ClearSelection;
  964.             end;
  965.         inherited Idle;
  966.     end;
  967.  
  968.     procedure TMapListDoc.SetEncounter (newEncounter: integer);
  969.         var
  970.             i: integer;
  971.     begin
  972.         gEncounter := newEncounter;
  973.         fVersion.encounter := newEncounter;
  974.         fImagesChanged := true;
  975.         UpdateImageViews;
  976.     end;
  977.  
  978. {$IFC FALSE}
  979.     procedure TMapListDoc.UpdateImageViews;
  980.         var
  981.             i: integer;
  982.     begin
  983.         if fImagesChanged then begin
  984.                 for i := 1 to fNumLevels do
  985.                     with fIndex^^[i] do
  986.                         if map <> nil then
  987.                             with TMapView(map.fView) do begin
  988.                                     Invalidate;
  989.                                     fPalette.ImagesChanged;
  990.                                 end;
  991.                 fImagesChanged := false;
  992.             end;
  993.     end;
  994. {$ENDC}
  995.  
  996. end.